// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.network.packets.vehicle;

import java.nio.ByteBuffer;
import zombie.core.network.ByteBufferWriter;
import zombie.core.physics.Bullet;
import zombie.core.physics.WorldSimulation;
import zombie.core.raknet.UdpConnection;
import zombie.network.GameClient;
import zombie.network.GameServer;
import zombie.network.PacketTypes;
import zombie.network.packets.INetworkPacket;
import zombie.vehicles.BaseVehicle;
import zombie.vehicles.VehicleInterpolationData;
import zombie.vehicles.VehicleManager;

public class Physics extends VehicleInterpolationData implements INetworkPacket {
    private static final float[] buffer = new float[27];
    protected short id;
    protected float force;
    private BaseVehicle vehicle;
    private boolean hasAuth;

    @Override
    public void parse(ByteBuffer b, UdpConnection connection) {
        this.id = b.getShort();
        this.time = b.getLong();
        this.force = b.getFloat();
        this.x = b.getFloat();
        this.y = b.getFloat();
        this.z = b.getFloat();
        this.qx = b.getFloat();
        this.qy = b.getFloat();
        this.qz = b.getFloat();
        this.qw = b.getFloat();
        this.vx = b.getFloat();
        this.vy = b.getFloat();
        this.vz = b.getFloat();
        this.engineSpeed = b.getFloat();
        this.throttle = b.getFloat();
        this.setNumWheels(b.getShort());

        for (int _int = 0; _int < this.wheelsCount; _int++) {
            this.wheelSteering[_int] = b.getFloat();
            this.wheelRotation[_int] = b.getFloat();
            this.wheelSkidInfo[_int] = b.getFloat();
            this.wheelSuspensionLength[_int] = b.getFloat();
        }

        this.vehicle = VehicleManager.instance.getVehicleByID(this.id);
        if (this.vehicle != null) {
            this.hasAuth = this.vehicle.hasAuthorization(connection);
        }
    }

    @Override
    public void write(ByteBufferWriter b) {
        b.putShort(this.id);
        b.putLong(this.time);
        b.putFloat(this.force);
        b.putFloat(this.x);
        b.putFloat(this.y);
        b.putFloat(this.z);
        b.putFloat(this.qx);
        b.putFloat(this.qy);
        b.putFloat(this.qz);
        b.putFloat(this.qw);
        b.putFloat(this.vx);
        b.putFloat(this.vy);
        b.putFloat(this.vz);
        b.putFloat(this.engineSpeed);
        b.putFloat(this.throttle);
        b.putShort(this.wheelsCount);

        for (int _int = 0; _int < this.wheelsCount; _int++) {
            b.putFloat(this.wheelSteering[_int]);
            b.putFloat(this.wheelRotation[_int]);
            b.putFloat(this.wheelSkidInfo[_int]);
            b.putFloat(this.wheelSuspensionLength[_int]);
        }
    }

    public boolean set(BaseVehicle _vehicle) {
        if (Bullet.getOwnVehiclePhysics(_vehicle.VehicleID, buffer) != 0) {
            return false;
        } else {
            this.id = _vehicle.getId();
            this.time = WorldSimulation.instance.time;
            this.force = _vehicle.getForce();
            int int0 = 0;
            this.x = buffer[int0++];
            this.y = buffer[int0++];
            this.z = buffer[int0++];
            this.qx = buffer[int0++];
            this.qy = buffer[int0++];
            this.qz = buffer[int0++];
            this.qw = buffer[int0++];
            this.vx = buffer[int0++];
            this.vy = buffer[int0++];
            this.vz = buffer[int0++];
            this.engineSpeed = (float)_vehicle.getEngineSpeed();
            this.throttle = _vehicle.throttle;
            this.wheelsCount = (short)((int)buffer[int0++]);

            for (int int1 = 0; int1 < this.wheelsCount; int1++) {
                this.wheelSteering[int1] = buffer[int0++];
                this.wheelRotation[int1] = buffer[int0++];
                this.wheelSkidInfo[int1] = buffer[int0++];
                this.wheelSuspensionLength[int1] = buffer[int0++];
            }

            return true;
        }
    }

    @Override
    public boolean isConsistent() {
        return INetworkPacket.super.isConsistent() && this.vehicle != null && (GameClient.bClient && !this.hasAuth || GameServer.bServer && this.hasAuth);
    }

    public void process() {
        if (this.isConsistent()) {
            if (GameClient.bClient) {
                this.vehicle.interpolation.interpolationDataAdd(this.vehicle, this);
            } else if (GameServer.bServer) {
                this.vehicle.setClientForce(this.force);
                this.vehicle.setX(this.x);
                this.vehicle.setY(this.y);
                this.vehicle.setZ(this.z);
                this.vehicle.savedRot.x = this.qx;
                this.vehicle.savedRot.y = this.qy;
                this.vehicle.savedRot.z = this.qz;
                this.vehicle.savedRot.w = this.qw;
                this.vehicle
                    .jniTransform
                    .origin
                    .set(this.vehicle.x - WorldSimulation.instance.offsetX, this.vehicle.z, this.vehicle.y - WorldSimulation.instance.offsetY);
                this.vehicle.jniTransform.setRotation(this.vehicle.savedRot);
                this.vehicle.jniLinearVelocity.x = this.vx;
                this.vehicle.jniLinearVelocity.y = this.vy;
                this.vehicle.jniLinearVelocity.z = this.vz;
                this.vehicle.engineSpeed = (double)this.engineSpeed;
                this.vehicle.throttle = this.throttle;
                this.setNumWheels(this.wheelsCount);

                for (int _int = 0; _int < this.wheelsCount; _int++) {
                    this.vehicle.wheelInfo[_int].steering = this.wheelSteering[_int];
                    this.vehicle.wheelInfo[_int].rotation = this.wheelRotation[_int];
                    this.vehicle.wheelInfo[_int].skidInfo = this.wheelSkidInfo[_int];
                    this.vehicle.wheelInfo[_int].suspensionLength = this.wheelSuspensionLength[_int];
                }
            }
        } else if (GameClient.bClient) {
            VehicleManager.instance.sendRequestGetFull(this.id, PacketTypes.PacketType.Vehicles);
        }
    }

    public boolean isRelevant(UdpConnection connection) {
        return connection.RelevantTo(this.x, this.y);
    }
}
